package com.zb.test;

import com.zb.bean.Employee;
import org.junit.Test;

import java.util.Optional;

/**
 *  Optional<T>类（java.util.Optional）是一个容器类,代表一个值存在或不存在，
 *     原来用null表示一个值不存在，现在Optionla可以更好的表达这个概念，并且可以避免空指针异常。
 */
public class JAVA8_10_Optional {
    /**
     * Optional容器类的常用方法：
     * 1.Optional.of(T t): 创建一个Optional实例
     * 2.Optional.empty(): 创建一个空的Optional实例
     * 3.Optional.ofNullable(T t): 若t不为null则创建Optional实例，否则创建一个空实例
     * 4.isPresent(): 判断Optional容器中是否包含值
     * 5.orElse(T t): 如果Optional容器包含值则返回这个值，否则返回t
     * 6.orElseGet(Supplier s): 如果调用对象包含值则返回该值，否则返回s获取的值
     * 7.map(Function f): 如果有值则对其处理，并返回处理后的Optional，否则返回一个Optional.empty()
     * 8.flatMap(Functrion f): 与map类似，要求必须返回一个Optional
     * 9.get(): 获取Optional容器中的值
     */

    //Optional.of(T t)
    @Test
    public void test1(){
        Optional op1 = Optional.of("123");
        Object obj = op1.get();//返回一个Object
        System.out.println(obj);
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

        //带泛型的Optional容器类
        Optional<Employee> op2 = Optional.of(new Employee(1,"张斌",26));
        Employee employee = op2.get();
        System.out.println(employee);
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");

        /*Optional.of()不可以创建一个为null的Optional容器，会报java.lang.NullPointerException异常
         * 但是可以快速定位到空指针异常的位置在 Optional.of(null)处
         * */
        Optional op3 = Optional.of(null);//java.lang.NullPointerException
        System.out.println(op3.get());
    }


    //Optional.empty()
    @Test
    public void test2(){
        Optional op = Optional.empty();//构建一个空的optional
        Object obj = op.get();//java.util.NoSuchElementException: No value present
        System.out.println(obj);
        /**
         * 可以构建一个空的Optional，但是获取不到值，因为没有值，所以提示No value present
         */
    }

    //Optional.ofNullable(T t)
    @Test
    public void test3(){
        Optional<Employee> op1 = Optional.ofNullable(new Employee(1,"zhangbin",26));
        Employee employee = op1.get();
        System.out.println(employee);

        System.out.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");

        Optional op2 = Optional.ofNullable(null);
        Object obj = op2.get();//java.util.NoSuchElementException: No value present
        System.out.println(obj);
        /**
         * Optional.ofNullable(T t)：如果T不为null则调用Optaion.of(T t)，否则调用Optional.empty()
         */
    }

    //isPresent()
    @Test
    public void Test4(){
        Optional op = Optional.ofNullable(null);
        if(op.isPresent()){//判断是否有值，有值返回true，无值返回false
            System.out.println("存在值");
        }else{
            System.out.println("不存在值");
        }
    }

    //orElse(T t)
    //orElseGet(Supplier s)
    @Test
    public void test5(){
        Optional op = Optional.ofNullable("111");
        Object obj = op.orElse("222");//op中有值，不hiU呗默认值代替
        System.out.println(obj);

        Optional op1 = Optional.ofNullable(null);
        Object obj1 = op1.orElse("333");//因为op1中没有值，所以被默认值"333"代替
        System.out.println(obj1);

        //orElseGet()和orElse的区别在于，orElseGet可以接受一个Supplier型函数式接口，可以做更多的操作
        Employee employee = (Employee) op1.orElseGet(() -> new Employee());
        System.out.println(employee);
    }

    //map(Function f)
    @Test
    public void test6(){
        Optional<Employee> op1 = Optional.ofNullable(new Employee(1,"zhangbin",26));
        Optional<String> op2 = op1.map((x) -> x.getName());
        System.out.println(op2.get());

        Optional<Employee> op3 = Optional.ofNullable(null);
        Optional<String> op4 = op3.map((x) -> x.getName());
        System.out.println(op4);//Optional.empty
        System.out.println(op4.get());//java.util.NoSuchElementException: No value present
    }

    //flatMap(Functrion f)
    @Test
    public void test7(){
        Optional<Employee> op1 = Optional.ofNullable(new Employee(1,"zhangbin",26));
        Optional<String> op2 = op1.flatMap((x) -> Optional.of(x.getName()));//接收的Function函数式接口的第二个参数需要一个Optional，对后返回的也是一个Optional
        System.out.println(op2.get());
    }

}
